﻿#region License
// MIT License
//
// Copyright(c) 2019-2025 ZhangYu
// https://gitee.com/zhangyu800/litebyte
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#endregion
#region Intro
// Purpose: Define base type value range
// Author: ZhangYu
// CreateDate: 2019-11-14
// LastModifiedDate: 2025-08-26
#endregion
namespace LiteByte.Common {

    #region Common
    public static class CommonUtil {

        #region Base Types
        // -------------------------------- 比特 | Bit --------------------------------
        private static readonly TypeData Bit1Type = new TypeData("bit1", TypeName.Bit1);
        private static readonly TypeData Bit2Type = new TypeData("bit2", TypeName.Bit2);
        private static readonly TypeData Bit3Type = new TypeData("bit3", TypeName.Bit3);
        private static readonly TypeData Bit4Type = new TypeData("bit4", TypeName.Bit4);
        private static readonly TypeData Bit5Type = new TypeData("bit5", TypeName.Bit5);
        private static readonly TypeData Bit6Type = new TypeData("bit6", TypeName.Bit6);
        private static readonly TypeData Bit7Type = new TypeData("bit7", TypeName.Bit7);
        private static readonly TypeData Bit8Type = new TypeData("bit8", TypeName.Bit8);
        // -------------------------------- 整数 | Integer --------------------------------
        private static readonly TypeData BoolType = new TypeData("bool", TypeName.Bool);
        private static readonly TypeData CharType = new TypeData("char", TypeName.Char);
        private static readonly TypeData UInt8Type = new TypeData("uint8", TypeName.UInt8);
        private static readonly TypeData UInt16Type = new TypeData("uint16", TypeName.UInt16);
        private static readonly TypeData UInt32Type = new TypeData("uint32", TypeName.UInt32);
        private static readonly TypeData UInt64Type = new TypeData("uint64", TypeName.UInt64);
        private static readonly TypeData Int8Type = new TypeData("int8", TypeName.Int8);
        private static readonly TypeData Int16Type = new TypeData("int16", TypeName.Int16);
        private static readonly TypeData Int32Type = new TypeData("int32", TypeName.Int32);
        private static readonly TypeData Int64Type = new TypeData("int64", TypeName.Int64);
        // -------------------------------- 浮点数 | Float --------------------------------
        private static readonly TypeData Float16Type = new TypeData("float16", TypeName.Float16);
        private static readonly TypeData Float32Type = new TypeData("float32", TypeName.Float32);
        private static readonly TypeData Float64Type = new TypeData("float64", TypeName.Float64);
        // -------------------------------- 变长整数 | Variable-Integer --------------------------------
        private static readonly TypeData VUInt16Type = new TypeData("vuint16", TypeName.VUInt16);
        private static readonly TypeData VUInt32Type = new TypeData("vuint32", TypeName.VUInt32);
        private static readonly TypeData VUInt64Type = new TypeData("vuint64", TypeName.VUInt64);
        private static readonly TypeData VInt16Type = new TypeData("vint16", TypeName.VInt16);
        private static readonly TypeData VInt32Type = new TypeData("vint32", TypeName.VInt32);
        private static readonly TypeData VInt64Type = new TypeData("vint64", TypeName.VInt64);
        private static readonly TypeData DecimalType = new TypeData("decimal", TypeName.Decimal);
        private static readonly TypeData DateTimeType = new TypeData("DateTime", TypeName.DateTime);
        // -------------------------------- 字符串 | String --------------------------------
        private static readonly TypeData VUnicodeType = new TypeData("vunicode", TypeName.VUnicode);
        private static readonly TypeData ASCIIType = new TypeData("ascii", TypeName.ASCII);
        private static readonly TypeData UTF8Type = new TypeData("utf8", TypeName.UTF8);
        private static readonly TypeData UTF16Type = new TypeData("utf16", TypeName.UTF16);
        private static readonly TypeData UTF32Type = new TypeData("utf32", TypeName.UTF32);
        private static readonly TypeData GBKType = new TypeData("gbk", TypeName.GBK);
        #endregion

        public static TypeData GetBaseType(string name) {
            switch (name) {
                case "bit1": return Bit1Type;
                case "bit2": return Bit2Type;
                case "bit3": return Bit3Type;
                case "bit4": return Bit4Type;
                case "bit5": return Bit5Type;
                case "bit6": return Bit6Type;
                case "bit7": return Bit7Type;
                case "bit8": return Bit8Type;
                case "bool" or "Boolean": return BoolType;
                case "char" or "Char": return CharType;
                case "uint8" or "byte" or "Byte": return UInt8Type;
                case "uint16" or "ushort" or "UInt16": return UInt16Type;
                case "uint32" or "uint" or "UInt32": return UInt32Type;
                case "uint64" or "ulong" or "UInt64": return UInt64Type;
                case "int8" or "sbyte" or "SByte": return Int8Type;
                case "int16" or "short" or "Int16": return Int16Type;
                case "int32" or "int" or "Int32": return Int32Type;
                case "int64" or "long" or "Int64": return Int64Type;
                case "float16" or "Half": return Float16Type;
                case "float32" or "float" or "Single": return Float32Type;
                case "float64" or "double" or "Double": return Float64Type;
                case "vuint16" or "vushort": return VUInt16Type;
                case "vuint32" or "vuint": return VUInt32Type;
                case "vuint64" or "vulong": return VUInt64Type;
                case "vint16" or "vshort": return VInt16Type;
                case "vint32" or "vint": return VInt32Type;
                case "vint64" or "vlong": return VInt64Type;
                case "decimal" or "Decimal": return DecimalType;
                case "DateTime": return DateTimeType;
                case "vunicode" or "string" or "String": return VUnicodeType;
                case "ascii": return ASCIIType;
                case "utf8": return UTF8Type;
                case "utf16": return UTF16Type;
                case "utf32": return UTF32Type;
                case "gbk": return GBKType;
                default: return null;
            }
        }

        public static bool IsList(string baseName, int genericTypeCount) {
            return genericTypeCount == 1 && baseName == "List";
        }

        public static bool IsHashMap(string baseName, int genericTypeCount) {
            return genericTypeCount == 2 && (baseName == "HashMap" || baseName == "Dictionary");
        }

        public static float GetByteSize(TypeName baseType) {
            switch (baseType) {
                case TypeName.Bit1: return 0.125f; // 1f / 8f
                case TypeName.Bit2: return 0.25f;  // 2f / 8f
                case TypeName.Bit3: return 0.375f; // 3f / 8f
                case TypeName.Bit4: return 0.5f;   // 4f / 8f
                case TypeName.Bit5: return 0.625f; // 5f / 8f
                case TypeName.Bit6: return 0.75f;  // 6f / 8f
                case TypeName.Bit7: return 0.875f; // 7f / 8f
                case TypeName.Bit8: return 1f;     // 8f / 8f
                case TypeName.Bool: return 1f;
                case TypeName.Char: return 2f;
                case TypeName.UInt8: return 1f;
                case TypeName.UInt16: return 2f;
                case TypeName.UInt32: return 4f;
                case TypeName.UInt64: return 8f;
                case TypeName.Int8: return 1f;
                case TypeName.Int16: return 2f;
                case TypeName.Int32: return 4f;
                case TypeName.Int64: return 8f;
                case TypeName.Float16: return 2f;
                case TypeName.Float32: return 4f;
                case TypeName.Float64: return 8f;
                case TypeName.VUInt16: return 1.125f; // (1f / 8f) + 1
                case TypeName.VUInt32: return 1.25f;  // (2f / 8f) + 1
                case TypeName.VUInt64: return 1.375f; // (3f / 8f) + 1
                case TypeName.VInt16: return 1.125f;  // (1f / 8f) + 1
                case TypeName.VInt32: return 1.25f;   // (2f / 8f) + 1
                case TypeName.VInt64: return 1.375f;  // (3f / 8f) + 1
                case TypeName.Decimal: return 5f;     // (4f / 8f) * 10
                case TypeName.DateTime: return 8.375f;// (3f / 8f) + 8
                case TypeName.VUnicode: return 5f;    // (2f / 8f + 1f) * 4;
                case TypeName.ASCII: return 4f;       // 1f * 4;
                case TypeName.UTF8: return 4f;        // 1f * 4;
                case TypeName.UTF16: return 8f;       // 2f * 4;
                case TypeName.UTF32: return 16f;      // 4f * 4;
                case TypeName.GBK: return 8f;         // 2f * 4;
                default: return 0;
            }
        }

    }
    #endregion

}